package org.zxyj.core.security;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author zhaoyong
 * @version 2016年3月3日
 */
public class DefaultPasswordService implements PasswordService {

	private static final Logger logger = LoggerFactory.getLogger(DefaultPasswordService.class);

	private static final String DEFAULT_DIGEST_ALGORITHMNAME = DigestAlgorithm.SHA1.name();

	private static final int DEFAULT_DIGEST_ITERATIONS = 1024;

	private static final int DEFAULT_PUBLICSALT_LENGTH = 8;

	private String algorithmName;

	private int iterations;

	private boolean generatePublicSalt;

	private int publicSaltLength = DEFAULT_PUBLICSALT_LENGTH;

	public DefaultPasswordService() {
		this.algorithmName = DEFAULT_DIGEST_ALGORITHMNAME;
		this.iterations = DEFAULT_DIGEST_ITERATIONS;
		this.generatePublicSalt = false;
	}

	public String encryptPassword(String plaintextPassword) throws IllegalArgumentException {
		byte[] salt = null;
		if (generatePublicSalt) {
			salt = Digests.generateSalt(publicSaltLength);
		}
		String plainPassword = Encodes.unescapeHtml(plaintextPassword);
		byte[] hashPassword = Digests.digest(plainPassword.getBytes(), algorithmName, salt, this.iterations);
		return (null == salt ? "" : Encodes.encodeHex(salt)) + Encodes.encodeHex(hashPassword);
	}

	public boolean passwordsMatch(String submittedPlaintext, String encrypted) {
		byte[] salt = null;
		if (generatePublicSalt) {
			// 从原密码中获取salt
			salt = Encodes.decodeHex(encrypted.substring(0, publicSaltLength * 2));
		}
		String plainPassword = Encodes.unescapeHtml(submittedPlaintext);
		byte[] hashPassword = Digests.digest(plainPassword.getBytes(), algorithmName, salt, this.iterations);
		return encrypted.equals((null == salt ? "" : Encodes.encodeHex(salt)) + Encodes.encodeHex(hashPassword));
	}

	public String getAlgorithmName() {
		return algorithmName;
	}

	public void setAlgorithmName(String algorithmName) throws AlgorithmNotSupportException {
		// 验证算法
		if (StringUtils.isEmpty(algorithmName) || null == DigestAlgorithm.valueOf(algorithmName)) {
			logger.warn("Not support this algorithm {} yet", algorithmName);
			throw new AlgorithmNotSupportException("Not support this algorithm yet");
		}
		this.algorithmName = algorithmName;
	}

	public int getIterations() {
		return iterations;
	}

	public void setIterations(int iterations) {
		if (iterations <= 0) {
			iterations = 1;
		}
		this.iterations = iterations;
	}

	public boolean isGeneratePublicSalt() {
		return generatePublicSalt;
	}

	public void setGeneratePublicSalt(boolean generatePublicSalt) {
		this.generatePublicSalt = generatePublicSalt;
	}

	public int getPublicSaltLength() {
		return publicSaltLength;
	}

	public void setPublicSaltLength(int publicSaltLength) {
		if (this.generatePublicSalt) {
			this.publicSaltLength = publicSaltLength;
		}
	}

}